/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.model.geo;

import java.awt.geom.Point2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class GCurve implements Serializable {
	
	private static final long serialVersionUID = 1L;
    private int label = 0;
    private ArrayList primitives = new ArrayList();
	private Point2D firstPoint;
	private Point2D endPoint;
	private GPoint[] discrete;
	
//*****************************************************************************
	
    public GCurve() {
	this.label = 0;
    }
	
//*****************************************************************************
	
    public GCurve(int x) {
	this.label = x;
    }
	
//*****************************************************************************
	
    public GCurve(int x, ArrayList y) {
	this.label = x;
	this.primitives = (ArrayList)y.clone();
	this.discrete();
    }
	
//*****************************************************************************
	
    public void setLabel(int lb) {
        this.label = lb;
    }
	
//*****************************************************************************
	
    public int getLabel( ) {
        return label;
    }
	
//*****************************************************************************
	
    public List getPrimitives( ) {
        return primitives;
    }
	
//*****************************************************************************
	
    public void setFirstPoint(Point2D p) {
        this.firstPoint = p;
    }
	
//*****************************************************************************
	
    public Point2D getFirstPoint( ) {
        return firstPoint;
    }
	
//*****************************************************************************
	
    public void setEndPoint(Point2D p) {
        this.endPoint = p;
    }
	
//*****************************************************************************
	
    public Point2D getEndPoint( ) {
        return endPoint;
    }
	
//*****************************************************************************
	
    public void setDiscrete(GPoint[] discret) {
		int NPoints = discret.length;
		this.discrete = new GPoint[NPoints];
		for (int i = 0; i<NPoints; i++) {
			this.discrete[i] = (GPoint)discret[i];
		}
    }
	
//*****************************************************************************
	
	private void discrete( ) {
		int np = 0;
		List prs = this.getPrimitives();
		ListIterator primitives = prs.listIterator();
		while(primitives.hasNext()) {
			Object primitive = primitives.next();
			if (primitive instanceof GPoint) {
				GPoint prt = (GPoint)primitive;
				np = np + prt.getNParts();
			}
			if (primitive instanceof GLine) {
				GLine prt = (GLine)primitive;
				np = np + prt.getNParts();
			}
			if (primitive instanceof GQuadCurve) {
				GQuadCurve prt = (GQuadCurve)primitive;
				np = np + prt.getNParts();
			}
			if (primitive instanceof GCubicCurve) {
				GCubicCurve prt = (GCubicCurve)primitive;
				np = np + prt.getNParts();
			}
		}
		int NPoints = np + 1;
		GPoint lastP = new GPoint();
		discrete = new GPoint[NPoints];
		int i = 0;
		int ndiv;
		primitives = prs.listIterator();
		while(primitives.hasNext()) {
			Object primitive = primitives.next();
			if (primitive instanceof GPoint) {
				GPoint prt = (GPoint)primitive;
				ndiv = prt.getNParts();
				GPoint[] pDiscrete = prt.getDiscrete();
				for (int k = 0; k < ndiv; k++) {
					discrete[i] = pDiscrete[0];
					i++;
					if ( i == np ) { lastP = pDiscrete[0]; }
				}
			}
			if (primitive instanceof GLine) {
				GLine prt = (GLine)primitive;
				ndiv = prt.getNParts();
				GPoint[] pDiscrete = prt.getDiscrete();
				double firstX = prt.getX1();
				double firstY = prt.getY1();
				if (pDiscrete[0].getX() == firstX && pDiscrete[0].getY() == firstY) {
					for (int k = 0; k < ndiv; k++) {
						discrete[i] = pDiscrete[k];
						i++;
						if ( i == np ) { lastP = pDiscrete[ndiv]; }
					}
				}else{
					for (int k = ndiv; k > 0; k--) {
						discrete[i] = pDiscrete[k];
						i++;
						if ( i == np ) { lastP = pDiscrete[0]; }
					}
				}
			}
			if (primitive instanceof GQuadCurve) {
				GQuadCurve prt = (GQuadCurve)primitive;
				ndiv = prt.getNParts();
				GPoint[] pDiscrete = prt.getDiscrete();
				double firstX = prt.getX1();
				double firstY = prt.getY1();
				if (pDiscrete[0].getX() == firstX && pDiscrete[0].getY() == firstY) {
					for (int k = 0; k < ndiv; k++) {
						discrete[i] = pDiscrete[k];
						i++;
						if ( i == np ) { lastP = pDiscrete[ndiv]; }
					}
				}else{
					for (int k = ndiv; k > 0; k--) {
						discrete[i] = pDiscrete[k];
						i++;
						if ( i == np ) { lastP = pDiscrete[0]; }
					}
				}
			}
			if (primitive instanceof GCubicCurve) {
				GCubicCurve prt = (GCubicCurve)primitive;
				ndiv = prt.getNParts();
				GPoint[] pDiscrete = prt.getDiscrete();
				double firstX = prt.getX1();
				double firstY = prt.getY1();
				if (pDiscrete[0].getX() == firstX && pDiscrete[0].getY() == firstY) {
					for (int k = 0; k < ndiv; k++) {
						discrete[i] = pDiscrete[k];
						i++;
						if ( i == np ) { lastP = pDiscrete[ndiv]; }
					}
				}else{
					for (int k = ndiv; k > 0; k--) {
						discrete[i] = pDiscrete[k];
						i++;
						if ( i == np ) { lastP = pDiscrete[0]; }
					}
				}
			}
		}
		discrete[np] = lastP;
	}
	
//*****************************************************************************
	
	public GPoint[] getDiscrete() {
		this.discrete();
		return discrete;
	}
	
//*****************************************************************************
	
	public GPoint[] getDiscrete(GPoint in) {
		this.discrete();
		if ( in.distance(discrete[0])==0 ) {
			return discrete;
		} else {
			GPoint[] discreteCCW = new GPoint[discrete.length];
			for (int k = 0; k < discrete.length; k++) {
				discreteCCW[k] = discrete[discrete.length-1-k];
			}
			return discreteCCW;
		}
	}
	
//*****************************************************************************
	
	public int getNPoints( ) {
		return discrete.length;
    }
	
//*****************************************************************************
}

